package com.example.robotica.appmobile.fragments;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.graphics.Color;
import android.opengl.GLSurfaceView;
import android.opengl.GLU;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import ar.com.untref.robotica.appmobile.R;


public class SensorFragment extends Fragment{

	private static final float ADVERTENCIA_DISTANCIA = 30f;
	private ObstaculoRenderer renderer;
	private static int DISTANCIA_MEDIA = 300;
	private TextView identificadorSensor;
	private TextView distanciaSensor;
	
	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
		return inflater.inflate(R.layout.fragmento_obstaculo, container, false);
	}
	
	@Override
	public void onViewCreated(View view, Bundle savedInstanceState) {
		
		super.onViewCreated(view, savedInstanceState);
		
		identificadorSensor = (TextView) getView().findViewById(R.id.identificador_sensor);
		distanciaSensor = (TextView) getView().findViewById(R.id.distancia_sensor);
		
		GLSurfaceView glSurfaceView = (GLSurfaceView) getView().findViewById(R.id.glSurfaceView);
		renderer = new ObstaculoRenderer();
		glSurfaceView.setRenderer(renderer);
	}
	
	public void setIdentificadorSensor(String identificador) {
		
		identificadorSensor.setText(identificador);
	}

	public void setDistancia(float distancia) {
		
		distanciaSensor.setText(String.valueOf(distancia));
		
		if (distancia < ADVERTENCIA_DISTANCIA) {
			distanciaSensor.setTextColor(Color.RED);
		}
		else {
			distanciaSensor.setTextColor(Color.WHITE);
		}
		
		float coeficienteDistancia = distancia / DISTANCIA_MEDIA;
		renderer.setCoeficienteDistancia(coeficienteDistancia);
	}
	
	public void setAngulo(float angulo) {
		
		renderer.setRotacionObstaculo(angulo);
	}

	private class ObstaculoRenderer implements GLSurfaceView.Renderer {

		private float coeficienteDistancia = 1f;
		private Obstaculo obstaculo = new Obstaculo();
		private float rotacionObstaculo;
		private int width;
		private int height;

		@Override
		public void onSurfaceCreated(GL10 gl, EGLConfig config) {

			gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
			gl.glClearDepthf(1.0f);
			gl.glEnable(GL10.GL_DEPTH_TEST);
			gl.glDepthFunc(GL10.GL_LEQUAL);

			gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
		}

		@Override
		public void onSurfaceChanged(GL10 gl, int width, int height) {

			this.width = width;
			this.height = height;
			gl.glViewport(0, 0, width, height);
			gl.glMatrixMode(GL10.GL_PROJECTION);
			gl.glLoadIdentity();
			gl.glViewport(0, 0, width, height);
			gl.glMatrixMode(GL10.GL_MODELVIEW);
			gl.glLoadIdentity();
		}

		@Override
		public void onDrawFrame(GL10 gl) {
			gl.glClear(GL10.GL_COLOR_BUFFER_BIT |  GL10.GL_DEPTH_BUFFER_BIT);
			gl.glLoadIdentity();
			
			GLU.gluPerspective(gl, 45.0f, ((float) width/(float) height) * getCoeficienteDistancia(), 0.1f, 200.0f);

			gl.glTranslatef(0.0f, 0.0f, -10.0f);
			gl.glRotatef(getRotacionObstaculo(), 0.0f, 1.0f, 0.0f);

			obstaculo.draw(gl);

			gl.glLoadIdentity();

		}

		public float getRotacionObstaculo() {
			return rotacionObstaculo;
		}

		public void setRotacionObstaculo(float rotacionObstaculo) {
			this.rotacionObstaculo = rotacionObstaculo;
		}

		public float getCoeficienteDistancia() {
			return coeficienteDistancia;
		}

		public void setCoeficienteDistancia(float coeficienteDistancia) {
			this.coeficienteDistancia = coeficienteDistancia;
		}

	}

	private class Obstaculo {

		private FloatBuffer mVertexBuffer;
		private FloatBuffer mColorBuffer;
		private ByteBuffer mIndexBuffer;

		// every 3 entries represent the 
		// position of one vertex
		private float[] vertices =
			{
				-3.0f, -1.0f, -1.0f, 
				3.0f, -1.0f, -1.0f, 
				3.0f, 1.0f, -1.0f, 
				-3.0f, 1.0f, -1.0f,
				-3.0f, -1.0f, 1.0f, 
				3.0f, -1.0f, 1.0f, 
				3.0f, 1.0f, 1.0f, 
				-3.0f, 1.0f, 1.0f
			};

		// every 4 entries represent the color (r,g,b,a) 
		// of the corresponding vertex in vertices
		private float[] colors =
			{
				0.0f, 1.0f, 0.0f, 1.0f, 
				0.0f, 1.0f, 0.0f, 1.0f, 
				1.0f, 0.5f, 0.0f, 1.0f, 
				1.0f, 0.5f, 0.0f, 1.0f, 
				1.0f, 0.0f, 0.0f, 1.0f, 
				1.0f, 0.0f, 0.0f, 1.0f,
				0.0f, 0.0f, 1.0f, 1.0f,
				1.0f, 0.0f, 1.0f, 1.0f
			};

		private byte[] indices =
			{
				0, 4, 5, 0, 5, 1, // two triangles for side 1
				1, 5, 6, 1, 6, 2, // two triangles for side 2
				2, 6, 7, 2, 7, 3, // etc.
				3, 7, 4, 3, 4, 0, 
				4, 7, 6, 4, 6, 5, 
				3, 0, 1, 3, 1, 2
			};

		public Obstaculo () {

			ByteBuffer byteBuf = ByteBuffer.allocateDirect(vertices.length * 4);
			byteBuf.order(ByteOrder.nativeOrder());
			mVertexBuffer = byteBuf.asFloatBuffer();
			mVertexBuffer.put(vertices);
			mVertexBuffer.position(0);

			byteBuf = ByteBuffer.allocateDirect(colors.length * 4);
			byteBuf.order(ByteOrder.nativeOrder());
			mColorBuffer = byteBuf.asFloatBuffer();
			mColorBuffer.put(colors);
			mColorBuffer.position(0);

			mIndexBuffer = ByteBuffer.allocateDirect(indices.length);
			mIndexBuffer.put(indices);
			mIndexBuffer.position(0);
		}

		public void draw(GL10 gl) {

			gl.glFrontFace(GL10.GL_CW);

			gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mVertexBuffer);
			gl.glColorPointer(4, GL10.GL_FLOAT, 0, mColorBuffer);

			gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
			gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

			// draw all 36 triangles
			gl.glDrawElements(GL10.GL_TRIANGLES, 36, GL10.GL_UNSIGNED_BYTE, mIndexBuffer);

			gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
			gl.glDisableClientState(GL10.GL_COLOR_ARRAY);
		}
	}
}
